/**
 * 
 */
package logic.algorithm;

import java.util.ArrayList;
import java.util.List;

import datamodel.Grid;
import datamodel.Grid.Neighbors;
import datamodel.GridElement;
import datamodel.GridElementAlgoState;
import datamodel.GridElementState;

/**
 * @author Marc, Kevin Munk
 * @version 0.1
 *
 */
public class ASternAlgorithm implements Algorithm {
	GridElement startgrid;	
	GridElement zielgrid;
	Neighbors neighbors;
	Grid grid;
	List<GridElement> queue;
	
	
	@Override
	public void init(Grid grid) {
		
		startgrid = grid.getStartElement();	
		zielgrid = grid.getEndElement();
		this.grid = grid;
		queue = new ArrayList<GridElement>();
		neighbors = grid.getNeighborsFrom(startgrid, true);
		
		for (int i = 0; i < grid.getRows(); i++) {
			for (int j = 0; j < grid.getColumns(); j++) {
				grid.getElementAt(i, j).setDistance(Integer.MAX_VALUE);
				grid.getElementAt(i, j).setPrevious(null);
				grid.getElementAt(i, j).setAlgoState(GridElementAlgoState.NONE);
			}
		}
		
		startgrid.setDistance(0);
		startgrid.setAlgoState(GridElementAlgoState.LOOKED_AT);
		
		for(int i=0; i < neighbors.getNeighbors().size();i++){
			GridElement neighbor = neighbors.getNeighbors().get(i);

			if(!neighbor.getState().equals(GridElementState.BLOCKED)){
				queue.add(neighbor);
				neighbor.setDistance(neighbors.getWayCosts().get(i));
				neighbor.setPrevious(startgrid);

			}
		}
	}
	
	
	
	@Override
	public boolean doNextStep() {
		while(!queue.isEmpty() && !zielgrid.getAlgoState().equals(GridElementAlgoState.LOOKED_AT)){

			GridElement minNode = queue.get(0);
			for(int n=0; n<queue.size();n++){

				double minNodeDis = minNode.getDistance() + mathcalc(minNode);
				double NodeDis = queue.get(n).getDistance() + mathcalc(queue.get(n));

				if(minNodeDis > NodeDis){
					minNode = queue.get(n);	
				}
			}
			queue.remove(minNode);
			minNode.setAlgoState(GridElementAlgoState.LOOKED_AT);

			neighbors = grid.getNeighborsFrom(minNode, true);

			for(int i=0; i < neighbors.getNeighbors().size();i++){

				GridElement neighbor = neighbors.getNeighbors().get(i);

				if(!neighbor.getState().equals(GridElementState.BLOCKED)){

					if(neighbor.getDistance() == Integer.MAX_VALUE){
						queue.add(neighbor);
					}
					if(minNode.getDistance()+neighbors.getWayCosts().get(i)<neighbor.getDistance()){
						neighbor.setDistance(minNode.getDistance()+neighbors.getWayCosts().get(i));
						neighbor.setPrevious(minNode);
					}
				}
			}
		}
		if(queue.isEmpty()){
			return false;
		}else{
			return !isSolved();}
	}

	@Override
	public boolean isSolved() {
		if(zielgrid.getDistance()!= Integer.MAX_VALUE){
			return true;
		}
		return false;
	}
	
	public double mathcalc(GridElement n){
		int X = n.getColumn() - zielgrid.getColumn();
		int Y = n.getRow() - zielgrid.getRow();
		
		return Math.sqrt(Math.pow(X, 2) + Math.pow(Y, 2))*4;
		
	}

}

	